#include <iostream>
#include <boost/program_options.hpp>
#include <string>
#include <math.h>
#include "get_arg.h"


// link with -lboost_filesystem-gcc -lboost_program_options-gcc
// program_options_helper.cpp

#define DEBUG_LEVEL 6
#include <debug_func.h>


// my functions
#include <print_error.h>
#include <program_options_helper.h>
using namespace BioCPP;




using std::vector;
using std::string;
using std::cerr;
using namespace program_options_helper;
namespace po = boost::program_options_lg;


//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888

//	select_matrix_file_format

//8888888888888888888888888888888888888888888888888888888888888888888888888888888888888888



//_______________________________________________________________________________________

//		process_command_line_options

//				from command line
//				Created [9/13/2001]

//_______________________________________________________________________________________
bool process_command_line_options(int argc, char* argv[], t_program_args& args)
{

//	char input_format;
	char output_format;


	// Hidden options to gather unused arguments
	po::positional_options_description left_over_positional_args;
	left_over_positional_args.add("left_over_args", -1);
	vector<string> left_overs;
	po::options_description left_over_args("Left Over Arguments");
	left_over_args.add_options()("left_over_args", 
							po::value< vector<string> >(), 
								"left_over_args")	;

	string pos_indices_str;
	args.optional_args.add_options()
//	("input_format,i", 		po::value<char>(&input_format)->default_value('p')->set_name("FORMAT"),
//								"Input FORMAT is FASTA ('f'), CLUSTAL ('c'), "
//								"or Phylip (PAML) ('p').")
    ("input_file,i",		po::value<string>(&args.file_input)
                                        ->set_name("FILE")
                                        ->default_value("STDIN"),
                                    "Sequence file in FASTA or CLUSTAL formats.")
	("output_format,o", 	po::value<char>(&output_format)
										->default_value('f')
										->set_name("FORMAT"),
								"Output FORMAT is FASTA ('f'), CLUSTAL ('c'), "
								"Phylip (PAML) ('p'), Non-interleaved Phylip ('n') or "
								"Tab-delimited ('t').")
	("positions,p", 		po::value<string>(&pos_indices_str)->set_name("INDICES"),
								"Indices of sequences to be retrived (starting from the 0th),\n"
								"where e.g. INDICES = \"1,3,9,11-13\".")
	("wrap_line,w", 		po::value<unsigned>(&args.line_wrap)->default_value(60)->set_name("LENGTH"),
								"Wrap FASTA, CLUSTAL or PHYLIP lines after LENGTH characters.\n"
								"0=Do not Wrap")
    ("names,n", 		    po::value<string>(&args.file_names)->set_name("FILE"),
                                    "FILE containing names of sequences to be retrieved.")
    ("regex,r", 			po::value<string>(&args.regex)
										->set_name("REGEX")
										->default_value("(\\S+)"),
								"Regular expression for identifying sequence names "
								"from the accession. "
								"Default to first group of non-whitespace letters.\n")
	("map_to_short_names,M",po::value<string>(&args.file_map_to_short_names)
                                        ->set_name("FILE"),
                                    "Use placeholder for sequence names in the form of "
                                    "VWXYZ00001, VWXYZ00001 etc.\n"
                                    "The supplied file will hold the relationship between "
                                    "the original names and the placeholders. Useful for "
                                    "the Phylip suite of programmes which expect names with "
                                    "fewer than 10 letters.")
    ("alphabetic_order,a",		"Print with names sorted alphabetically");

	args.add_std_options();
	po::options_description all_args("");
	all_args.add(args.optional_args).add(left_over_args);
	po::options_description visible_args("");
	visible_args.add(args.optional_args);

	// parse command line
	po::variables_map vm;
	po::store(po::command_line_parser(argc, argv)
			  .options(all_args)
			  .positional(left_over_positional_args).run(), vm);
	po::notify(vm);

	bool print_help_and_exit = false;
	if (vm.count("left_over_args"))
		print_help_and_exit = true;

	if (vm.count("version"))
	{
		print_version(cerr, *argv, "1.1\n"
			"\tHistory: \n\n"
			"\tv 1.0\1"
			"Initial version\1NB Phylip import may still not work properly. Contact me if so.\n"
			);
		return false;
	}
	if (vm.count("help") || print_help_and_exit)
	{
		string exe_description =
				"Takes a sequence file and outputs it in the specified format.\n"
				"The sequences filtered to only include names matching those specified "
				"via STDIN (--names). Names are matched against the accessions using "
				"a regular expression.\n"
				"If --positions is not specified, only sequences with accessions matching "
				"REGEX will be retained.\n"
				"N.B. Duplicates are allowed. E.g. --positions \"1,1,2,2\".\n";
		print_usage(cerr, string(*argv), "--sequences FILE [OPTIONS]",
											visible_args, exe_description, 80);
		if (vm.count("left_over_args"))
		{
			cerr << "\tError:\n\tThe file with the names of sequences should be specified "
					"\n\tvia STDIN and not the command line.\n\n";
		}
		return false;
	}
	//check_required_options(vm, mandatory_args);

	args.alpha		= vm.count("alphabetic_order");
	args.header		= vm.count("header");
	args.names		= vm.count("names");

//	select_sequence_file_format(input_format, args.input_format, "input format");
	BioCPP::select_sequence_file_format(output_format, args.output_format, "output format");

	// check pair indices
	try
	{
		parse_indices(pos_indices_str, args.pos_indices);
	}
	catch (std::runtime_error& err)
	{
		throw std::runtime_error(string("--position INDICES incorrectly specified:\n") +
											err.what());
	}

	args.open_err_log();
	return true;
}




